package com.koron.plan.web.statistic.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.koron.bean.base.Response;
import com.koron.common.core.business.datadict.utils.DataDictTool;
import com.koron.plan.web.feign.OperationFeign;
import com.koron.plan.web.feign.OrderFeign;
import com.koron.plan.web.feign.dto.IntactRatioDto;
import com.koron.plan.web.statistic.Enum.StatInfoEnum;
import com.koron.plan.web.statistic.entity.IntactRatioPO;
import com.koron.plan.web.statistic.entity.StatPO;
import com.koron.plan.web.statistic.mapper.StatMapper;
import com.koron.plan.web.statistic.service.NanShaDataStatistic;
import com.koron.plan.web.statistic.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;


/**
 * 数仓统计
 */
@Service
@Slf4j
public class NanShaDataStatisticImpl implements SchedulingConfigurer, NanShaDataStatistic, InitializingBean {


    public static Map<String, String> CORN_CONFIG = new HashMap<String, String>();

    // 每个月的1号零点
    public static String DEFAULT_MONTH_CORN = "0 0 1 1/1 * ? ";
    //public static String DEFAULT_MONTH_CORN = "0 0/1 * * * ? ";

    // 每年的1月1号零点
    public static String DEFAULT_YEAR_CORN = "0 0 0 1 1 ? ";
    //public static String DEFAULT_YEAR_CORN = "0 0/1 * * * ? ";

    private boolean enabled;

    @Autowired
    OrderFeign orderFeign;

    @Autowired
    OperationFeign operationFeign;

    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            CORN_CONFIG = DataDictTool.getDataDictByCode("systemManagement", "statCornConfig");
            this.enabled = Boolean.valueOf(CORN_CONFIG.get("enabled"));
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    /**
     * 水司租户
     *
     * @return
     */
    private String getCurrDs() {
        return "water_03";
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

        if (enabled) {
            try {
                NanShaDataStatisticImpl service = SpringUtil.getBean(NanShaDataStatisticImpl.class);
                // 统计类型：1-月，2-年
                List<Integer> types = Arrays.asList(1, 2);
                // 消缺率
                for (Integer type : types) {
                    if (1 == type) {

                        taskRegistrar.addTriggerTask(() -> {
                            // 消缺率
                            ADOConnection.runTask(getCurrDs(), service, "staOrderHandleRate", Void.class, null, null, 1);
                            // 消缺及时率
                            ADOConnection.runTask(getCurrDs(), service, "staOrderHandleRateTimely", Void.class, null, null, 1);
                            // 设备正常率
                            ADOConnection.runTask(getCurrDs(), service, "staDeviceNormalRate", Void.class, 1, null);


                        }, new CronTrigger(getCustomMonthCron("")));

                    } else if (2 == type) {

                        taskRegistrar.addTriggerTask(() -> {
                            // 年度消缺率
                            ADOConnection.runTask(getCurrDs(), service, "staOrderHandleRate", Void.class, null, null, 2);
                            // 年度消缺及时率
                            ADOConnection.runTask(getCurrDs(), service, "staOrderHandleRateTimely", Void.class, null, null, 2);
                            // 年度设备正常率
                            ADOConnection.runTask(getCurrDs(), service, "staDeviceNormalRate", Void.class, 2, null);

                        }, new CronTrigger(getCustomYearCron("")));
                    }
                }
            } catch (Exception e) {
                log.error("数仓统计定时任务异常：" + e.getMessage());
            }
        }
    }

    public static String getCustomMonthCron(String key) {
        return StrUtil.isNotBlank(CORN_CONFIG.get(key)) ? CORN_CONFIG.get(key) : DEFAULT_MONTH_CORN;
    }

    public static String getCustomYearCron(String key) {
        return StrUtil.isNotBlank(CORN_CONFIG.get(key)) ? CORN_CONFIG.get(key) : DEFAULT_YEAR_CORN;
    }

    /**
     * 统计设备完好率：
     * 水厂、黄阁水厂、榄核水厂
     */
    @TaskAnnotation("staDeviceNormalRate")
    @Override
    public void staDeviceNormalRate(SessionFactory sessionFactory, Integer type, IntactRatioDto intactRatioDto) {
        StatMapper statMapper = sessionFactory.getMapper(StatMapper.class);
        if (Objects.isNull(intactRatioDto)) {
            intactRatioDto = new IntactRatioDto();
            intactRatioDto.setStartMonth(LocalDate.now().getMonth().getValue() - 1);
            intactRatioDto.setEndMonth(LocalDate.now().getMonth().getValue() - 1);
            intactRatioDto.setYear(type == 1 ? LocalDate.now().getYear() : LocalDate.now().getYear() - 1);
        }
        // 获取设备正常率
        Response<Object> response = operationFeign.intactRatioDetails(intactRatioDto);
        if (Objects.isNull(response) || Objects.isNull(response.getData())) {
            log.error("设备完好率不存在！");
            return;
        }

        List<IntactRatioPO> intactRatioPOS = new ArrayList();
        JSONObject jsonObject = JSONUtil.parseObj(response);

        if (Objects.nonNull(jsonObject)) {
            JSONArray data = jsonObject.getJSONArray("data");
            data.stream().forEach(d -> {
                JSONArray unitDept = ((JSONObject) d).getJSONArray("unitDet");
                if (Objects.nonNull(unitDept)) {
                    JSONObject intactRatio = (JSONObject) unitDept.stream().filter(u -> getUnit(((String) ((JSONObject) u).get("deptName")))).findFirst().orElseGet(() -> null);
                    if (Objects.nonNull(intactRatio)) {
                        String deptName = (String) intactRatio.get("deptName");
                        BigDecimal yearIntactRate = (BigDecimal) intactRatio.getByPath("yearItems.intactRate");
                        Integer monthIntactRate = (Integer) intactRatio.getByPath(String.format("monthItems[%d].intactRate", LocalDate.now().getMonth().getValue() - 1));

                        IntactRatioPO intactRatioPO = new IntactRatioPO();
                        intactRatioPO.setName(deptName);
                        intactRatioPO.setMonthIntactRate(Double.valueOf(monthIntactRate));
                        intactRatioPO.setYearIntactRate(yearIntactRate.doubleValue());
                        intactRatioPOS.add(intactRatioPO);
                    }
                }
                // 获取公司合计
                if (getUnit((String) ((JSONObject) d).get("deptName"))) {
                    String deptName = (String) ((JSONObject) d).get("deptName");
                    BigDecimal yearIntactRate = (BigDecimal) ((JSONObject) d).getByPath("yearItems.intactRate");
                    BigDecimal monthIntactRate = (BigDecimal) ((JSONObject) d).getByPath(String.format("monthItems[%d].intactRate", LocalDate.now().getMonth().getValue() - 1));

                    IntactRatioPO intactRatioPO = new IntactRatioPO();
                    intactRatioPO.setName("水司");
                    intactRatioPO.setMonthIntactRate(monthIntactRate.doubleValue());
                    intactRatioPO.setYearIntactRate(yearIntactRate.doubleValue());
                    intactRatioPOS.add(intactRatioPO);
                }
            });
        }

        if (CollectionUtils.isNotEmpty(intactRatioPOS)) {
            for (IntactRatioPO intactRatioPO : intactRatioPOS) {
                StatPO statPO = new StatPO();
                statPO.setName(intactRatioPO.getName());

                statPO.setValue(type == 1 ? intactRatioPO.getMonthIntactRate() : intactRatioPO.getYearIntactRate());
                statPO.setCreateTime(new Date());
                if (type == 1) {
                    statPO.setCode(getCode(intactRatioPO.getName(),"MONTH"));
                    statPO.setYear(LocalDate.now().getYear());
                    statPO.setMonth(LocalDate.now().getMonth().getValue() - 1);

                    // 插入数据
                    log.info("设备正常率处理完成！");
                    statMapper.saveStatMonth(statPO);
                } else if (type == 2) {
                    statPO.setCode(getCode(intactRatioPO.getName(),"YEAR"));
                    statPO.setYear(LocalDate.now().getYear() - 1);
                    statPO.setMonth(null);
                    // 插入数据
                    log.info("设备正常率处理完成！");
                    statMapper.saveStatYear(statPO);
                }
            }
        }

    }

    private String getCode(String name, String type) {
        switch (name) {
            case "黄阁水厂":
                return StatInfoEnum.HGSC_SC_HGSCSBWHL.getCode() + "_" + type;
            case "榄核水厂":
                return StatInfoEnum.LHSC_SC_LHSCSBWHL.getCode() + "_" + type;
            case "水司":
                return StatInfoEnum.SS_SC_SBWHL.getCode() + "_" + type;
            default:
                return null;
        }
    }

    private static boolean getUnit(String deptName) {
        List<String> unit = Arrays.asList("黄阁水厂", "榄核水厂", "公司合计");
        return unit.contains(deptName);
    }


    /**
     * 统计黄阁水厂设备完好率
     */
    @Override
    public void staDeviceNormalByHG(SessionFactory sessionFactory) {
    }

    /**
     * 统计榄核水厂设备完好率
     */
    @Override
    public void staDeviceNormalByLH(SessionFactory sessionFactory) {
    }


    /**
     * 统计工单消缺率
     */
    @TaskAnnotation("staOrderHandleRate")
    @Override
    public void staOrderHandleRate(SessionFactory sessionFactory, String startTime, String endTime, Integer type) {
        switch (type) {
            case 1:
                staOrderHandleRateByMonth(sessionFactory, startTime, endTime);
                break;
            case 2:
                staOrderHandleRateByYear(sessionFactory, startTime, endTime);
                break;
            default:
                throw new RuntimeException("统计类型错误");
        }

    }

    /**
     * 统计工单消缺及时率
     */
    @TaskAnnotation("staOrderHandleRateTimely")
    @Override
    public void staOrderHandleRateTimely(SessionFactory sessionFactory, String startTime, String endTime, Integer type) {
        switch (type) {
            case 1:
                staOrderHandleRateTimelyByMonth(sessionFactory, startTime, endTime);
                break;
            case 2:
                staOrderHandleRateTimelyByYear(sessionFactory, startTime, endTime);
                break;
            default:
                throw new RuntimeException("统计类型错误");
        }
    }

    private void staOrderHandleRateTimelyByYear(SessionFactory sessionFactory, String startTime, String endTime) {
        StatMapper statMapper = sessionFactory.getMapper(StatMapper.class);
        String currDs = getCurrDs();
        String date = DateUtil.getYear();

        if (StrUtil.isBlank(startTime)) {
            startTime = DateUtil.getLastYear();
        }

        if (StrUtil.isBlank(endTime)) {
            endTime = DateUtil.getCurYear();
        }

        Response<Object> response = orderFeign.defectRateInTime(currDs, startTime, endTime);
        if (response != null && response.getData() != null) {
            Double rate = (Double) response.getData();
            log.info("统计工单消缺及时率：rate=" + rate);

            StatPO statPO = new StatPO();
            statPO.setCode("SS_SC_XQCLJSL_YEAR");
            statPO.setName("消缺处理及时率");
            statPO.setValue(rate);
            statPO.setYear(LocalDate.now().getYear()-1);
            statPO.setMonth(null);
            statPO.setCreateTime(new Date());

            // 保存到数据库中
            statMapper.saveStatYear(statPO);
            log.info("年度工单消缺率统计完成！");
        } else {
            log.error("统计工单消缺及时率：response=" + response);
        }
    }

    private void staOrderHandleRateTimelyByMonth(SessionFactory sessionFactory, String startTime, String endTime) {
        StatMapper statMapper = sessionFactory.getMapper(StatMapper.class);
        String currDs = getCurrDs();
        String date = DateUtil.getMonth();

        if (StrUtil.isBlank(startTime)) {
            startTime = DateUtil.getFirstDayOfMonth();
        }

        if (StrUtil.isBlank(endTime)) {
            endTime = DateUtil.getLastDayOfMonth();
        }

        Response<Object> response = orderFeign.defectRateInTime(currDs, startTime, endTime);
        if (response != null && response.getData() != null) {
            Double rate = (Double) response.getData();
            log.info("统计工单消缺及时率：rate=" + rate);


            StatPO statPO = new StatPO();
            statPO.setCode("SS_SC_XQCLJSL_MONTH");
            statPO.setName("消缺处理及时率");
            statPO.setValue(rate);
            statPO.setYear(LocalDate.now().getYear());
            statPO.setMonth(LocalDate.now().getMonth().getValue() - 1);
            statPO.setCreateTime(new Date());

            // 保存到数据库中
            statMapper.saveStatMonth(statPO);
            log.info("月度工单消缺及时率统计完成！");
        } else {
            log.error("统计工单消缺及时率：response=" + response);
        }
    }


    private void staOrderHandleRateByYear(SessionFactory sessionFactory, String startTime, String endTime) {
        StatMapper statMapper = sessionFactory.getMapper(StatMapper.class);
        String currDs = getCurrDs();
        String date = DateUtil.getYear();

        if (StrUtil.isBlank(startTime)) {
            startTime = DateUtil.getLastYear();
        }

        if (StrUtil.isBlank(endTime)) {
            endTime = DateUtil.getCurYear();
        }

        Response<Object> response = orderFeign.defectRate(currDs, startTime, endTime);
        if (response != null && response.getData() != null) {
            Double rate = (Double) response.getData();
            log.info("统计工单消缺率：rate=" + rate);

            StatPO statPO = new StatPO();
            statPO.setCode("SS_SC_XQL_YEAR");
            statPO.setName("消缺率");
            statPO.setValue(rate);
            statPO.setYear(LocalDate.now().getYear()-1);
            statPO.setCreateTime(new Date());

            // 保存到数据库中
            statMapper.saveStatYear(statPO);
            log.info("年度工单消缺率统计完成！");
        } else {
            log.error("统计工单消缺率：response=" + response);
        }
    }

    private void staOrderHandleRateByMonth(SessionFactory sessionFactory, String startTime, String endTime) {
        StatMapper statMapper = sessionFactory.getMapper(StatMapper.class);
        String currDs = getCurrDs();
        String date = DateUtil.getMonth();

        if (StrUtil.isBlank(startTime)) {
            startTime = DateUtil.getFirstDayOfMonth();
        }

        if (StrUtil.isBlank(endTime)) {
            endTime = DateUtil.getLastDayOfMonth();
        }

        Response<Object> response = orderFeign.defectRate(currDs, startTime, endTime);
        if (response != null && response.getData() != null) {
            Double rate = (Double) response.getData();
            log.info("统计工单消缺率：rate=" + rate);

            StatPO statPO = new StatPO();
            statPO.setCode("SS_SC_XQL_MONTH");
            statPO.setName("消缺率");
            statPO.setValue(rate);
            statPO.setCreateTime(new Date());
            statPO.setYear(LocalDate.now().getYear());
            statPO.setMonth(LocalDate.now().getMonth().getValue() - 1);

            // 保存到数据库中
            statMapper.saveStatMonth(statPO);
            log.info("月度工单消缺率统计完成！");
        } else {
            log.error("统计工单消缺率：response=" + response);
        }

    }

    public String doHttp() {
        String url = "https://eamv2.guangdongwater.com:8001/eam-service-operation/intactratio/intactRatioDetails?80024";
        IntactRatioDto intactRatioDto = new IntactRatioDto();
        intactRatioDto.setStartMonth(1);
        intactRatioDto.setEndMonth(12);
        intactRatioDto.setYear(2024);

        String body = JSONUtil.toJsonStr(intactRatioDto);

        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MTMwNTQ5NDgsImFjY291bnQiOiJnYW95dWFuIn0.P92KiZ_bHBe6-K3-SCqKu7w1uyuk0uegVzUDE7cmw5k";
        String post = HttpUtil.createPost(url).header("token", token).header("Dynamic_data_source", "water_03").body(body).execute().body();
        return post;
    }



}
